﻿#define _CRT_SECURE_NO_WARNINGS 1

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickItem>

#include <QDebug>

#include <winsock.h>
#include <Windows.h>
#include <io.h>
#include <fcntl.h>

#include <string>
#include <iostream>

#pragma comment(lib, "ws2_32.lib")

using namespace std;

unsigned __stdcall receiveMessages(void* param);

class ChatClient : public QObject {
    Q_OBJECT
public:
    explicit ChatClient(QObject *parent = nullptr) : QObject(parent), serverSocket(INVALID_SOCKET)
    {
        // 初始化网络
        //initNetwork();
        connect(this, &ChatClient::internalMessageReceived,
                this, &ChatClient::onMessageReceived);
    }

    void initNetwork() {
        WSADATA wsaDATA;
        WSAStartup(MAKEWORD(2, 2), &wsaDATA);
        if (LOBYTE(wsaDATA.wVersion) != 2 || HIBYTE(wsaDATA.wVersion) != 2)
            qDebug() << L"Wrong Version";

        serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (SOCKET_ERROR == serverSocket)
            qDebug() << L"Socket Error";

        SOCKADDR_IN sAddr = { 0 };
        sAddr.sin_family = AF_INET;
        sAddr.sin_addr.S_un.S_addr = inet_addr("192.168.10.12");
        sAddr.sin_port = htons(9527);

        if ((int)::connect(serverSocket, (sockaddr*)&sAddr, sizeof sAddr) == -1)
            qDebug() << L"Connect Error";
        else
            qDebug() << L"已连接到服务器";
    }

    // 增加安全退出方法
    void stop() {
        if(serverSocket != INVALID_SOCKET) {
            closesocket(serverSocket);
            serverSocket = INVALID_SOCKET;
        }
    }

    ~ChatClient() {
        closesocket(serverSocket);
        WSACleanup();
    }

    Q_INVOKABLE void sendMessage(const QString &message) {
        string msg = message.toStdString();
        send(serverSocket, msg.c_str(), msg.size(), 0);
    }

    Q_INVOKABLE bool login(const QString &username, const QString &password)
    {
        // 发送登录请求
        string msg = "LOGIN:" + username.toStdString() + ":" + password.toStdString();
        string name = username.toStdString();
        send(serverSocket, name.c_str(), name.size(), 0);
        send(serverSocket, msg.c_str(), msg.size(), 0);

        qDebug() << "send login";

        // 等待登录响应
        char response[256];
        int r = recv(serverSocket, response, 255, 0);
        if (r <= 0) return false;

        response[r] = 0;

        qDebug() << "login back message";

        if(strcmp(response, "LOGIN_SUCCESS") == 0)
        {
            HANDLE hThread = (HANDLE)_beginthreadex(0, 0, receiveMessages, this, 0, 0);
        }

        return strcmp(response, "LOGIN_SUCCESS") == 0;
    }

    Q_INVOKABLE bool changePassword(const QString &oldPassword, const QString &newPassword) {
        string msg = "CHANGE_PW:" + oldPassword.toStdString() + ":" + newPassword.toStdString();
        send(serverSocket, msg.c_str(), msg.size(), 0);

        char response[256];
        int r = recv(serverSocket, response, 255, 0);
        if (r <= 0) return false;

        response[r] = 0;
        return strcmp(response, "PW_CHANGE_SUCCESS") == 0;
    }

signals:
    void messageReceived(const QString &message);
    void internalMessageReceived(const QString &message); // 内部信号

private slots:
    void onMessageReceived(const QString &msg) {
        // 主线程中处理消息
        emit messageReceived(msg);
    }

public:
    SOCKET serverSocket;
};

unsigned __stdcall receiveMessages(void* param)
{
    ChatClient* client = static_cast<ChatClient*>(param);
    char recvBuff[256];

    while (client->serverSocket != INVALID_SOCKET)
    {
        int r = recv(client->serverSocket, recvBuff, 255, NULL);
        if (r > 0) {
            recvBuff[r] = 0;

            // 处理服务器命令
            if (strncmp(recvBuff, "CMD:", 4) == 0)
            {
                // 添加命令处理
                continue;
            }

            QString msg = QString::fromUtf8(recvBuff);
            emit client->messageReceived(msg);
        }
        else
        {
            emit client->internalMessageReceived("连接已断开");
            break;
        }
    }

    return 0;
}

int main(int argc, char *argv[])
{
    qDebug() << "客户端启动中...";

    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    // 将聊天客户端暴露给QML
    ChatClient chatClient;
    engine.rootContext()->setContextProperty("chatClient", &chatClient);

    // 加载QML界面
    engine.loadFromModule("ChatClientQt", "Main");

    // 获取根对象
    QObject *rootObject = engine.rootObjects().first();
    if (!rootObject) {
        qDebug() << "加载QML失败";
        return -1;
    }

    // 连接消息接收信号
    QObject::connect(&chatClient, &ChatClient::messageReceived,
                     [rootObject](const QString &msg) {
                         QMetaObject::invokeMethod(rootObject, "appendMessage",
                                                   Q_ARG(QVariant, msg));
                     });

    // 连接服务器
    chatClient.initNetwork();

    int ret = app.exec();

    return ret;
}

#include "main.moc"
